001    /**
002     * Created by IntelliJ IDEA.
003     * User: Wei Wang
004     * Date: Mar 2, 2003
005     * Time: 9:05:11 PM
006     */
007    
008    package EVolve.visualization;
009    
010    import javax.swing.*;
011    import java.awt.*;
012    import java.awt.event.MouseAdapter;
013    import java.awt.event.MouseEvent;
014    import java.awt.event.MouseMotionAdapter;
015    import java.awt.image.BufferedImage;
016    import java.awt.geom.AffineTransform;
017    import java.awt.geom.Point2D;
018    import java.awt.geom.Rectangle2D;
019    import java.util.ArrayList;
020    
021    public class AxesPanel extends JPanel{
022        public final static int Axis_Enabled = 0x00001;
023        public final static int Scale_Image = 0x00010;
024        public final static int Flip_Image = 0x00100;
025        public final static int Pointer_Enabled = 0x01000;
026        public final static int Box_Enabled = 0x10000;
027        public final static int Null = 0x0;
028    
029        private int flag;
030        private String xName=" ", yName=" ";
031        private Point origin, imageAdjustment, pointerPosition;
032        private Point boxStart, boxEnd;
033        private Point2D.Double mousePos;
034        private int zoomingWidth, zoomingHeight, shapeSize;
035        private BufferedImage image;
036        private JScrollPane parent = null;
037        private ArrayList phases;
038    
039        public AxesPanel(int flag) {
040            this.flag = flag;
041            origin = new Point(0,0);
042            imageAdjustment = new Point(0,0);
043            pointerPosition = new Point(0,0);
044            boxStart = new Point(0,0);
045            boxEnd = new Point(0,0);
046            mousePos = new Point2D.Double(0,0);
047            zoomingWidth = zoomingHeight = 20;
048            shapeSize = 1;
049            if ((flag & 0x000f) == Axis_Enabled) {
050                origin.setLocation(20,20);
051                imageAdjustment.x = 60;
052                imageAdjustment.y = 60;
053            }
054            addMouseListener(new MouseAdapter() {
055                public void mousePressed(MouseEvent e) {
056                    if (e.getButton() == MouseEvent.BUTTON1) {
057                        mPressed(e.getX(), e.getY());
058                    }
059                }
060            });
061    
062            addMouseListener(new MouseAdapter() {
063                public void mouseReleased(MouseEvent e) {
064                    if (e.getButton() == MouseEvent.BUTTON1) {
065                        mReleased();
066                    }
067                }
068            });
069    
070            addMouseMotionListener(new MouseMotionAdapter() {
071                public void mouseDragged(MouseEvent e) {
072                    mDragged(e.getX(), e.getY());
073                }
074            });
075        }
076    
077        private void drawAxis(Graphics2D g2) {
078    
079            if ((flag & 0x000f)==Axis_Enabled) {//axis is enabled
080                int w = getWidth(), h = getHeight();
081                g2.setColor(Color.black);
082                g2.drawLine(origin.x, h - origin.y, w - origin.x, h - origin.x);
083                g2.drawLine(w - origin.x, h - origin.y, w - 30, h - 15);
084                g2.drawLine(w - origin.x, h - origin.y, w - 30, h - 25);
085                g2.drawLine(origin.x, h - origin.y, origin.x, origin.y);
086                g2.drawLine(origin.x, origin.y, 15, 30);
087                g2.drawLine(origin.x, origin.y, 25, 30);
088    
089    
090                Font font = new Font("Arial", Font.PLAIN, 12);
091                g2.setFont(font);
092                g2.drawString(xName, w - g2.getFontMetrics().stringWidth(xName) - 40, h - 5);
093                g2.rotate(-Math.PI / 2.0);
094                g2.drawString(yName, -40 - g2.getFontMetrics().stringWidth(yName), 15);
095                g2.rotate(Math.PI / 2.0);
096            }
097        }
098    
099        private void drawImage(Graphics2D g2) {
100            int w = getWidth(), h = getHeight(), flip = 1;
101            AffineTransform tf = g2.getTransform();
102    
103            if ((flag&0x0f00)==Flip_Image) {
104                flip = -1;
105                g2.translate(origin.x+1, h - origin.y);
106            }
107    
108            if ((flag&0x00f0)==Scale_Image) {
109                g2.scale((double)(w - imageAdjustment.x) / (double)(image.getWidth()),
110                         (double)flip * (double)(h - imageAdjustment.y) / (double)(image.getHeight()));
111                g2.drawImage(image, 0, 0, null);
112            } else {
113                if ((flag&0x0000f) == Axis_Enabled) {
114                    g2.scale(1,flip);
115                }
116                g2.drawImage(image, 0, 0, null);
117            }
118            g2.setTransform(tf);
119        }
120    
121        private void drawBox(Graphics2D g2) {
122            g2.setColor(Color.blue);
123            int x1 = (boxStart.x < boxEnd.x) ? boxStart.x : boxEnd.x;
124            int x2 = (boxStart.x > boxEnd.x) ? boxStart.x : boxEnd.x;
125            int y1 = (boxStart.y < boxEnd.y) ? boxStart.y : boxEnd.y;
126            int y2 = (boxStart.y > boxEnd.y) ? boxStart.y : boxEnd.y;
127            g2.drawRect(x1, y1, x2 - x1, y2 - y1);
128        }
129    
130        private void drawPhases(Graphics2D g2) {
131            double xFactor = 1;
132            int w = getWidth(), h = getHeight();
133    
134            if (phases == null) return;
135    
136            if ((flag&0x00f0)==Scale_Image) {
137                xFactor = (double)(w - imageAdjustment.x) / (double)(image.getWidth());
138            }
139    
140            g2.setColor(Color.black);
141            for (int i=0; i<phases.size(); i++) {
142                int phaseEnd = ((Integer)phases.get(i)).intValue();
143    
144                if (phaseEnd <= 0) continue;
145    
146                g2.drawString(String.valueOf(phaseEnd),(int)(phaseEnd*xFactor)+origin.x,10);
147                g2.drawLine((int)(phaseEnd*xFactor)+origin.x, h-origin.y, (int)(phaseEnd*xFactor)+origin.x, origin.y);
148            }
149    
150        }
151    
152        private void drawPointer(Graphics2D g2) {
153            if ((flag&0xf000)==Pointer_Enabled) {
154                int x = pointerPosition.x, y = pointerPosition.y;
155                g2.setColor(Color.black);
156                g2.drawLine(x,y,x+20,y+20);
157                g2.drawLine(x,y,x+10,y+5);
158                g2.drawLine(x,y,x+5,y+10);
159            }
160        }
161    
162        private void setPreferredPanelSize() {
163            if (parent == null) return;
164    
165            if ((flag&0x000f0) != Scale_Image) {
166                setPreferredSize(new java.awt.Dimension(image.getWidth()+imageAdjustment.x,image.getHeight()+imageAdjustment.y));
167            } else {
168                setPreferredSize(new java.awt.Dimension(parent.getWidth()-14, parent.getHeight()-14));
169            }
170            revalidate();
171        }
172    
173        public void paintComponent(Graphics g) {
174            super.paintComponent(g);
175    
176            Graphics2D g2 = (Graphics2D)g;
177    
178            int w = getWidth();
179            int h = getHeight();
180    
181            g2.setColor(Color.white);
182            g2.fillRect(0, 0, w, h);
183    
184            drawAxis(g2);
185    
186            if (image != null) {
187                setPreferredPanelSize();
188                drawImage(g2);
189                drawBox(g2);
190                drawPhases(g2);
191            }
192            drawPointer(g2);
193    
194        }
195    
196        protected void mPressed(int x, int y) {
197            if (image != null) {
198                boxStart.x = x;
199                boxStart.y = y;
200                boxEnd.x = x;
201                boxEnd.y = y;
202                flag = flag | Box_Enabled;
203                repaint();
204            }
205        }
206    
207        protected void mReleased() {
208            if (image != null) {
209                flag = flag & 0x0ffff;
210            }
211        }
212    
213        protected void mDragged(int x, int y) {
214            if ((image != null)&&((flag &0xf0000) == Box_Enabled)) {
215                boxEnd.x = x;
216                boxEnd.y = y;
217                repaint();
218            }
219        }
220    
221        public void setName(String xName, String yName) {
222            this.xName = xName;
223            this.yName = yName;
224        }
225    
226        public void setImage(BufferedImage image) {
227            this.image = image;
228    
229            boxStart.x = 0;
230            boxStart.y = 0;
231            boxEnd.x = 0;
232            boxEnd.y = 0;
233            flag = flag & 0x0ffff;
234        }
235    
236        public int getImageX(int x) {
237            if (image == null) return -1;
238    
239            if ((flag & 0x000f0) == Scale_Image)
240                return (int)((float)(x-origin.x)*((float)image.getWidth()/(float)(getWidth()-imageAdjustment.x)));
241            else
242                return x - origin.x;
243        }
244    
245        public int getImageY(int y) {
246            if (image == null) return -1;
247    
248            if ((flag & 0x000f0) == Scale_Image) {
249                if ((flag & 0x00f00) == Flip_Image)
250                    return (int)((float)(getHeight()-origin.y-y)*((float)image.getHeight()/(float)(getHeight()-imageAdjustment.y)));
251                else
252                    return (int)((float)(y-origin.y)*((float)image.getHeight()/(float)(getHeight()-imageAdjustment.y)));
253            }
254            else {
255                if ((flag & 0x00f00) == Flip_Image)
256                    return getHeight()-origin.y-y;
257                else
258                    return y - origin.y;
259            }
260        }
261    
262        public int getStartX() {
263            int x = (boxStart.x < boxEnd.x) ? boxStart.x : boxEnd.x;
264            return getImageX(x);
265        }
266    
267        public int getEndX() {
268            int x = (boxStart.x > boxEnd.x) ? boxStart.x : boxEnd.x;
269            return getImageX(x);
270        }
271    
272        public int getStartY() {
273            int y = (boxStart.y < boxEnd.y) ? boxStart.y : boxEnd.y;
274            return getImageY(y);
275        }
276    
277        public int getEndY() {
278            int y = (boxStart.y > boxEnd.y) ? boxStart.y : boxEnd.y;
279            return getImageY(y);
280        }
281    
282        public void setPointerPosition(int x, int y) {
283            pointerPosition.x = x;
284            pointerPosition.y = y;
285        }
286    
287        public void enablePointer(boolean draw) {
288            if (draw)
289                flag = flag | Pointer_Enabled;
290            else
291                flag = flag & (~Pointer_Enabled);
292        }
293    
294        private Rectangle2D.Double calcZoomingArea(int x, int y) {
295            int w = image.getWidth(), h = image.getHeight();
296    
297            double x1=x,y1=y,w1,h1;
298    
299            x1 = x1 - (double)zoomingWidth*shapeSize/2;
300            y1 = y1 - (double)zoomingHeight*shapeSize/2;
301    
302            w1 = zoomingWidth*shapeSize;
303            h1 = zoomingHeight*shapeSize;
304    
305            mousePos.setLocation(shapeSize*zoomingWidth/2,shapeSize*zoomingHeight/2);
306            if (x1 < 0) {
307                mousePos.x+=x1;
308                w1 = w1+x1;
309                x1 = 0;
310            }
311            if (x1 + w1 > w) {
312                w1 = w - x1;
313            }
314    
315            if (y1 < 0) {
316                mousePos.y+=y1;
317                h1 = h1+y1;
318                y1 = 0;
319            }
320            if (y1 + h1 > h) {
321                h1 = h - y1;
322            }
323    
324            Rectangle2D.Double ret = new Rectangle2D.Double();
325            ret.x = x1;
326            ret.y = y1;
327            ret.width = w1;
328            ret.height = h1;
329            return ret;
330        }
331    
332        public BufferedImage getSubImage(int x, int y) {
333            int w = image.getWidth(), h = image.getHeight();
334            Rectangle2D.Double zooming = calcZoomingArea(x,y);
335    
336            if ((image == null)||(zooming.x>w)||(zooming.y>h))
337                return null;
338    
339            if ((zooming.width<=0) || (zooming.height<=0)) return null;
340    
341            return image.getSubimage((int)zooming.x,(int)zooming.y,(int)zooming.width,(int)zooming.height);
342        }
343    
344        public void drawZoomingArea(int x, int y) {
345            double coX = 1, coY = 1;
346    
347            if ((flag & 0x00f0) == Scale_Image) {
348                coX = (double)(getWidth() - imageAdjustment.x)/(double)image.getWidth();
349                coY = (double)(getHeight() - imageAdjustment.y)/(double)image.getHeight();
350            }
351            int deltaX = (int)(coX*zoomingWidth*shapeSize/2);
352            int deltaY = (int)(coY*zoomingHeight*shapeSize/2);
353    
354            boxStart.x = x - deltaX;
355            boxStart.y = y - deltaY;
356            boxEnd.x = x + deltaX;
357            boxEnd.y = y + deltaY;
358            flag = flag | Box_Enabled;
359            repaint();
360            flag = flag & (~Box_Enabled);
361        }
362    
363        public void setShapeSize(int shapeSize) {
364            this.shapeSize = shapeSize;
365        }
366    
367        public void setZoomingSize(int w, int h) {
368            zoomingWidth = w;
369            zoomingHeight = h;
370        }
371    
372        public Point2D.Double getMouseMovement() {
373            return mousePos;
374        }
375    
376        public void scaleImage(boolean scaled) {
377            if (scaled)
378                flag = flag | Scale_Image;
379            else
380                flag = flag & (~Scale_Image);
381        }
382    
383        public void setParent(JScrollPane parent) {
384            this.parent = parent;
385        }
386    
387        public void setPanelFlag(int flag) {
388            this.flag = flag;
389            if ((flag & 0x000f) != Axis_Enabled) {
390                origin.setLocation(0,0);
391                imageAdjustment.x = 0;
392                imageAdjustment.y = 0;
393            }
394        }
395    
396        public Point getOrigin() {
397            return origin;
398        }
399    
400        public void setPhases(ArrayList phases) {
401            this.phases = phases;
402        }
403    
404        public Object clone() {
405            AxesPanel o = new AxesPanel(flag);
406    
407            o.xName = xName;
408            o.yName = yName;
409            o.zoomingWidth = zoomingWidth;
410            o.zoomingHeight = zoomingHeight;
411            o.shapeSize = shapeSize;
412            return o;
413        }
414    }